/**
 * @brief 书上程序
 *      注意: 在 window 上的文本文件在换行前有一个 \r
 *          符号,会造成程序错误
 * 
 * @file message.cpp
 * @author your name
 * @date 2018-09-03
 */
#include <iostream>
#include <vector>
#include <string>
#include <map>
#include <fstream>

using namespace std;
/**
 * @brief 邮件类
 *      只存储指向单个邮件的头尾指针，所有邮件文本行均存在 vector<string> 中
 */
class Message
{
    using Line_iter = vector<string>::const_iterator;
    Line_iter first;
    Line_iter last;

  public:
    Message(Line_iter p1, Line_iter p2) : first{p1}, last{p2} {};
    Line_iter begin() const { return first; };
    Line_iter end() const { return last; };
};
/**
 * @brief 判断某字符串是否为前缀（标志）
 * 
 * @param line 文本行
 * @param s 待查字符串
 * @return int 返回前缀或标志结束位置
 */
int is_prefix(const string &line, const string &s)
{
    int n = s.size();
    if (string(line, 0, n) == s)
        return n;
    return 0;
}
/**
 * @brief 通过 From: 标志 查找发件人和地址
 *      找到就返回 true 否则 false
 * @param m 邮件指针
 * @param s 输出：发件人和地址
 * @return true 
 * @return false 
 */
bool find_from_addr(const Message *m, string &s)
{
    int n;
    for (auto iter = m->begin(); iter != m->end(); ++iter)
    {
        n = is_prefix(*iter, "From: ");
        if (n)
        {
            s = string(*iter, n);
            return true;
        }
    }
    return false;
}
/**
 * @brief 查找文件的主题并返回
 * 
 * @param m 邮件指针
 * @return string 返回的主题
 */
string find_subject(const Message* m)
{
    int n;
    for(auto iter = m->begin(); iter != m->end(); ++iter)
    {
        n = is_prefix(*iter, "Subject: ");
        if(n)
        {
            return string(*iter, n);
        }
    }

    return "";
}
/**
 * @brief 总邮件文件，存储文本行和邮件
 * 
 */
struct Mail_file
{
    using Message_iter = vector<Message>::const_iterator;
    vector<string> lines;
    vector<Message> m;

    Mail_file(const string &f);
    Message_iter begin() const { return m.begin(); }
    Message_iter end() const { return m.end(); }
};

Mail_file::Mail_file(const string &f)
{
    ifstream in{f};
    if (!in)
        cerr << "open file error\n";
    // 必须先存完 lines 不能同时判断 Message 因为迭代器会失效
    for (string s; getline(in, s);)
        lines.push_back(s);

    auto first = lines.begin();
    for (auto iter = lines.begin(); iter != lines.end(); ++iter)
    {
        if (*iter == "----")
        {
            m.push_back(Message(first, iter));
            first = iter + 1; // 不能自加
        }
    }
}

int main()
{
    Mail_file mfile("message.txt");
    
    multimap<string, const Message*> sender;

    string s;
    for(auto message_iter = mfile.begin(); message_iter!= mfile.end(); ++message_iter)
    {
        // 虽然都指向 message 但他们的类型可能不一样，注意
        if(find_from_addr(&(*message_iter), s))
            sender.insert(make_pair(s, &(*message_iter)));
    }

    auto pp = sender.equal_range("ding<ding>");
    for(auto p = pp.first; p != pp.second; ++p)
        cout << find_subject(p->second) << "\n";

    return 0;
}